import time

import logzero
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QGridLayout, QGroupBox, QLabel, QWidget

from helpers.mengy_bytes_helper import bytes2Int
import mengy_spac800
import mengy_spac800_bt

logger = logzero.setup_logger("tabs.7.fault_info")


class Tab_7_Fault_Info(QWidget):
    def __init__(self, serRecvDir, logger=logger):
        super().__init__()
        self.serRecvDir = serRecvDir
        self.logger = logger
        self.initUI()
        self.refreshTime = time.time()
        self.logger.info("this is tab7 fault info logger")
        self.setObjectName("tab7")
        layout = QGridLayout(self)
        layout.addWidget(self.faultInfoGroupBox, 0, 0, 1, 1)  # 故障信息

    def initUI(self):
        """初始化显示构件"""
        self.createFaultInfoGroupBox()

    def createFaultInfoGroupBox(self):
        self.faultInfoGroupBox = QGroupBox("故障信息")
        layout = QGridLayout(self.faultInfoGroupBox)
        self.fault_Ws = []
        self.faultSubGBs = []
        for idx, faultGroup in enumerate(mengy_spac800.FAULT_NAME):
            name = mengy_spac800.FAULT_GROUP_NAME[idx]
            blen = len(mengy_spac800.FAULT_NAME[idx])
            subGB = QGroupBox("{}-{:0{}b}".format(name, 0, blen))
            subLayout = QGridLayout(subGB)
            subFault = []
            for i, f in enumerate(faultGroup):
                subFault.append(QLabel(f))
                subFault[i].setAlignment(Qt.AlignCenter)
                if idx == 0:
                    subLayout.addWidget(subFault[i], i % 15, i // 15)
                elif idx == 1:
                    subLayout.addWidget(subFault[i], i, 0)
                elif idx == 2:
                    subLayout.addWidget(subFault[i], i % 15, i // 15)
                elif idx == 3:
                    subLayout.addWidget(subFault[i], i % 15, i // 15)
            self.fault_Ws.append(subFault)
            self.faultSubGBs.append(subGB)
        layout.addWidget(self.faultSubGBs[0], 0, 0, 1, 2)
        layout.addWidget(self.faultSubGBs[1], 0, 2, 1, 1)
        layout.addWidget(self.faultSubGBs[2], 0, 3, 1, 2)
        layout.addWidget(self.faultSubGBs[3], 0, 5, 1, 2)

    def faultInfoRead(self):
        raw = tuple(self.serRecvDir.get(i) for i in range(0x0E00, 0x0E07 + 1))
        if any((i is None for i in raw)):
            return
        data = tuple(bytes2Int(i) for i in raw)
        dealData = [data[2 * i] + (data[2 * i + 1] << 16) for i in range(4)]
        for ws, gb, d in zip(self.fault_Ws, self.faultSubGBs, dealData):
            # self.logger.info(f'fault d {d:08X}')
            idx = self.faultSubGBs.index(gb)
            name = mengy_spac800.FAULT_GROUP_NAME[idx]
            blen = len(mengy_spac800.FAULT_NAME[idx])
            gb.setTitle("{}-{:0{}b}".format(name, 0, blen))
            for i, w in enumerate(ws):
                if d & (1 << i):
                    w.setStyleSheet("background-color:#ff0000; color:#000000")
                else:
                    w.setStyleSheet("background-color:#00ff00; color:#FFFFFF")

    def updateBySerialRecvBuff(self, changeAddrList):
        """数据缓存发生变化时需要刷新部分"""
        if any(i in changeAddrList for i in range(0x0E00, 0x0E07 + 1)):
            self.faultInfoRead()
            self.refreshTime = time.time()

    def updateByTimer(self, timeout=1):
        if time.time() - self.refreshTime > timeout:
            self.faultInfoRead()
            self.refreshTime = time.time()

    def updateUnconditional(self):
        """无条件刷新界面显示部分"""
        pass

    def updateWhole(self):
        """更新全体显示构件"""
        self.faultInfoRead()
        self.refreshTime = time.time()


class Tab_7_Fault_Info_BT(Tab_7_Fault_Info):
    def createFaultInfoGroupBox(self):
        self.faultInfoGroupBox = QGroupBox("故障信息")
        layout = QGridLayout(self.faultInfoGroupBox)
        self.fault_Ws = []
        self.faultSubGBs = []
        for idx, faultGroup in enumerate(mengy_spac800_bt.FAULT_NAME):
            name = mengy_spac800_bt.FAULT_GROUP_NAME[idx]
            blen = len(mengy_spac800_bt.FAULT_NAME[idx])
            subGB = QGroupBox("{}-{:0{}b}".format(name, 0, blen))
            subLayout = QGridLayout(subGB)
            subFault = []
            for i, f in enumerate(faultGroup):
                subFault.append(QLabel(f))
                subFault[i].setAlignment(Qt.AlignCenter)
                if idx == 0:
                    subLayout.addWidget(subFault[i], i, 0)
                elif idx == 1:
                    subLayout.addWidget(subFault[i], i, 0)
                elif idx == 2:
                    subLayout.addWidget(subFault[i], i, 0)
                elif idx == 3:
                    subLayout.addWidget(subFault[i], i % 28, i // 28)
            self.fault_Ws.append(subFault)
            self.faultSubGBs.append(subGB)
        layout.addWidget(self.faultSubGBs[0], 0, 0, 30, 1)
        layout.addWidget(self.faultSubGBs[1], 0, 1, 12, 1)
        layout.addWidget(self.faultSubGBs[2], 12, 1, 18, 1)
        layout.addWidget(self.faultSubGBs[3], 0, 2, 30, 3)

    def faultInfoRead(self):
        raw = tuple(self.serRecvDir.get(i) for i in range(0x0E00, 0x0E0B + 1))
        if any((i is None for i in raw)):
            return
        data = tuple(bytes2Int(i) for i in raw)
        dealData = [data[2 * i] + (data[2 * i + 1] << 16) for i in range(3)]
        for ws, gb, d in zip(self.fault_Ws[:3], self.faultSubGBs, dealData):
            # self.logger.info(f"fault d {d:08X}")
            idx = self.faultSubGBs.index(gb)
            name = mengy_spac800_bt.FAULT_GROUP_NAME[idx]
            blen = len(mengy_spac800_bt.FAULT_NAME[idx])
            gb.setTitle("{}-{:0{}b}".format(name, 0, blen))
            for i, w in enumerate(ws):
                if d & (1 << i):
                    w.setStyleSheet("background-color:#ff0000; color:#000000")
                else:
                    w.setStyleSheet("background-color:#00ff00; color:#FFFFFF")

        dealData = [data[2 * i + 6] + (data[2 * i + 7] << 16) for i in range(3)]
        gb = self.faultSubGBs[-1]
        name = mengy_spac800_bt.FAULT_GROUP_NAME[-1]
        blen = len(mengy_spac800_bt.FAULT_NAME[-1])
        gb.setTitle("{}-{:0{}b}".format(name, 0, blen))
        # self.logger.debug("faultInfoRead last | {:032b} {:032b} {:032b}".format(*dealData))
        for i, w in enumerate(self.fault_Ws[3]):
            if dealData[i // 32] & (1 << (i % 32)):
                w.setStyleSheet("background-color:#ff0000; color:#000000")
            else:
                w.setStyleSheet("background-color:#00ff00; color:#FFFFFF")

    def updateBySerialRecvBuff(self, changeAddrList):
        """数据缓存发生变化时需要刷新部分"""
        if any(i in changeAddrList for i in range(0x0E00, 0x0E0B + 1)):
            self.faultInfoRead()
            self.refreshTime = time.time()
